﻿using System;
using System.Collections.Generic;
using System.Text;
using PreguntaAlExperto.TransporterObjectsFramework;
using PreguntaAlExperto.RulesLayer.Entities;
using PreguntaAlExperto.ObjectMapper;
using PreguntaAlExperto.ObjectMapper.DTO;
using PreguntaAlExperto;

namespace PreguntaAlExperto.RulesLayer.Services
{
    public class ArticlesService
    {

        public BaseList<Article> getAllArticles()
        {
            ArticlesDTO _DTO = new ArticlesDTO();
            BaseList<Article> _articles = (BaseList<Article>)_DTO.Select("SQL_SELECT_ALL_ARTICLES", null);

            foreach (Article _article in _articles)
            { 
                PublisherService _pService = new PublisherService();
                _article.PublisherEntity = (Publisher)_pService.getPublisherByID(_article.Publisher_ID);
            }
            return _articles;
        }

        public BaseList<Article> getRelatedArticles(int GroupID)
        { 
            ArticlesDTO _DTO = new ArticlesDTO();
            SearchCriteria _searchCriteria = new SearchCriteria();
            _searchCriteria.addParameter("@GROUP_ID", GroupID);
            BaseList<Article> _articles = (BaseList<Article>)_DTO.Select("SQL_SELECT_ARTICLE_BY_GROUP", _searchCriteria);

            foreach (Article _article in _articles)
            {
                PublisherService _pService = new PublisherService();
                _article.PublisherEntity = (Publisher)_pService.getPublisherByID(_article.Publisher_ID);
            }

            return _articles;
        }

        public BaseList<Article> getNewArticles()
        {
            ArticlesDTO _DTO = new ArticlesDTO();
            BaseList<Article> _articles = (BaseList<Article>)_DTO.Select("SQL_SELECT_NEW_ARTICLES", null);

            foreach (Article _article in _articles)
            { 
                PublisherService _pService = new PublisherService();
                _article.PublisherEntity = (Publisher)_pService.getPublisherByID(_article.Publisher_ID);
                if (_article.Short_Description.Length > 250)
                    _article.Short_Description = _article.Short_Description.Substring(0, 249) + "...";
            }

            return _articles;
        }

        public BaseList<Article> getTopTeenVisited()
        {
            ArticlesDTO _DTO = new ArticlesDTO();
            BaseList<Article> _articles = (BaseList<Article>)_DTO.Select("SQL_SELECT_TOP10_VISITS", null);

            foreach (Article _article in _articles)
            {
                PublisherService _pService = new PublisherService();
                _article.PublisherEntity = (Publisher)_pService.getPublisherByID(_article.Publisher_ID);
            }

            return _articles;            
        }

        public BaseList<Article> getTopTeenVoted()
        {
            ArticlesDTO _DTO = new ArticlesDTO();
            BaseList<Article> _articles = (BaseList<Article>)_DTO.Select("SQL_SELECT_TOP10_VOTES", null);

            foreach (Article _article in _articles)
            {
                PublisherService _pService = new PublisherService();
                _article.PublisherEntity = (Publisher)_pService.getPublisherByID(_article.Publisher_ID);
            }

            return _articles;            
        }

        public bool updateVisit(string Path)
        {
            SearchCriteria _searchCriteria = new SearchCriteria();
            _searchCriteria.addParameter("@PATH", Path);

            ArticlesDTO _DTO = new ArticlesDTO();
            try
            {
                _DTO.Update("SQL_UPDATE_VISIT_TO_ARTICLE", _searchCriteria);
                return true;
            }
            catch
            {
                return false;
            }        
        }

        public int PublishArticle(Article _article)
        {
            SearchCriteria _searchCriteria = new SearchCriteria();
            _searchCriteria.addParameter("@Publisher_ID", _article.Publisher_ID);
            _searchCriteria.addParameter("@Path", _article.Path);
            _searchCriteria.addParameter("@Title", _article.Title);
            _searchCriteria.addParameter("@Short_Description", _article.Short_Description);
            _searchCriteria.addParameter("@Publish_Date", _article.Publish_Date);
            _searchCriteria.addParameter("@AllowedToPublish", _article.AllowedToPublish);

            SingleValueDTO _DTO = new SingleValueDTO();
            int _ArticleID = int.Parse(_DTO.Select("SQL_INSERT_NEW_ARTICLE", _searchCriteria).ToString());

            List<SearchCriteria> values = new List<SearchCriteria>();
            List<string> queries = new List<string>();
            foreach (Pair _element in _article.Technologies)
            {
                SearchCriteria _item = new SearchCriteria();
                _item.addParameter("@ARTICLE_ID", _ArticleID);
                _item.addParameter("@TECHNOLOGY_ID", _element.ID);
                values.Add(_item);
                queries.Add("SQL_INSERT_ARTICLES_TECHNOLOGIES");
            }

            foreach (Pair _element in _article.Skills)
            {
                SearchCriteria _item = new SearchCriteria();
                _item.addParameter("@ARTICLE_ID", _ArticleID);
                _item.addParameter("@SKILL_ID", _element.ID);
                values.Add(_item);
                queries.Add("SQL_INSERT_ARTICLES_SKILL");
            }

            foreach (Pair _element in _article.Platforms)
            {
                SearchCriteria _item = new SearchCriteria();
                _item.addParameter("@ARTICLE_ID", _ArticleID);
                _item.addParameter("@PLATFORM_ID", _element.ID);
                values.Add(_item);
                queries.Add("SQL_INSERT_ARTICLES_PLATFORM");
            }

            foreach (Pair _element in _article.Languages)
            {
                SearchCriteria _item = new SearchCriteria();
                _item.addParameter("@ARTICLE_ID", _ArticleID);
                _item.addParameter("@LANGUAGE_ID", _element.ID);
                values.Add(_item);
                queries.Add("SQL_INSERT_ARTICLES_LANGUAGES");
            }

            ArticlesDTO _ArticleDTO = new ArticlesDTO();
            _ArticleDTO.AdvancedActualization(queries, values);

            return _ArticleID;
        }

        public Article getArticleByPath(string Path)
        { 
            ArticlesDTO _DTO = new ArticlesDTO();
            SearchCriteria _searchCriteria = new SearchCriteria();
            _searchCriteria.addParameter("@PATH", Path);
            BaseList<Article> _articles = (BaseList<Article>)_DTO.Select("SQL_SELECT_ARTICLE_BY_PATH", _searchCriteria);

            foreach (Article _article in _articles)
            { 
                PublisherService _pService = new PublisherService();
                _article.PublisherEntity = (Publisher)_pService.getPublisherByID(_article.Publisher_ID);
            }

            if (0 == _articles.Count)
                throw new ArticleNotFoundException();

            return _articles[0];
        }

        public void updateVote(string Path, int Vote)
        { 
            ArticlesDTO _DTO = new ArticlesDTO();
            SearchCriteria _searchCriteria = new SearchCriteria();
            _searchCriteria.addParameter("@PATH", Path);
            _searchCriteria.addParameter("@POINTS", Vote);
            _DTO.Update("SQL_UPDATE_VOTES_ARTICLE", _searchCriteria);
        }

        public void CommentArticle(int ArticleID, int UserID, string Comment)
        { 
            SearchCriteria _searchCriteria = new SearchCriteria();
            SingleValueDTO _DTO = new SingleValueDTO();
            _searchCriteria.addParameter("@ARTICLEID", ArticleID);
            _searchCriteria.addParameter("@USERID", UserID);
            _searchCriteria.addParameter("@COMMENT", Comment);

            _DTO.Select("SQL_INSERT_NEW_COMMENT", _searchCriteria);
        }

        public bool MarkForFollowArticle(int ArticleID, int UserId, bool Follow)
        {
            SearchCriteria _searchCriteria = new SearchCriteria();
            _searchCriteria.addParameter("@ARTICLEID", ArticleID);
            _searchCriteria.addParameter("@USERID", UserId);
            if (Follow)
            {
                SingleValueDTO _DTO = new SingleValueDTO();
                _DTO.Select("SQL_INSERT_FOLLOW_COMMENT", _searchCriteria);
                return true;
            }
            else
            {
                SingleValueDTO _DTO = new SingleValueDTO();
                _DTO.Select("SQL_DELETE_FOLLOW_COMMENT", _searchCriteria);
                return false;
            }
        }

        public bool GetFollowArticleStatus(int ArticleID, int UserId)
        {
            SearchCriteria _searchCriteria = new SearchCriteria();
            _searchCriteria.addParameter("@ARTICLEID", ArticleID);
            _searchCriteria.addParameter("@USERID", UserId);
            SingleValueDTO _DTO = new SingleValueDTO();
            int _result = (int)_DTO.Select("SQL_SELECT_FOLLOW_COMMENT", _searchCriteria);
            if (_result > 0)
                return true;
            else
                return false;
        }

        public BaseList<Followers> getFollowers(int Article_ID)
        { 
            SearchCriteria _searchCriteria = new SearchCriteria();
            _searchCriteria.addParameter("@ARTICLEID", Article_ID);
            FollowersDTO _DTO = new FollowersDTO();
            return (BaseList<Followers>)_DTO.Select("SQL_SELECT_FOLLOWERS_BY_ARTICLE", _searchCriteria);
            
        }

        public BaseList<Comments> getComments(int ArticleID)
        { 
            SearchCriteria _searchCriteria = new SearchCriteria();
            _searchCriteria.addParameter("@ARTICLEID", ArticleID);
            CommentsDTO _DTO = new CommentsDTO();

            return (BaseList<Comments>)_DTO.Select("SQL_SELECT_COMMENT_BY_ARTICLES", _searchCriteria);
        }

        public BaseList<SiteMap> getSiteMap()
        {
            SiteMapDTO _DTO = new SiteMapDTO();
            return (BaseList<SiteMap>)_DTO.Select("SQL_SELECT_SITEMAP", null);
        }

        public List<Article> getArticleByPublisher(Publisher publisher)
        {
            ArticlesDTO _DTO = new ArticlesDTO();
            SearchCriteria _searchCriteria = new SearchCriteria();
            _searchCriteria.addParameter("@PUBLISHER_ID", publisher.ID_Publisher );
            BaseList<Article> _articles = (BaseList<Article>)_DTO.Select("SQL_SELECT_ARTICLE_BY_PUBLISHER", _searchCriteria);

            foreach (Article _article in _articles)
            {
                PublisherService _pService = new PublisherService();
                _article.PublisherEntity = (Publisher)_pService.getPublisherByID(_article.Publisher_ID);
            }

            return _articles;
        }

        public Article getArticleById(string postid)
        {
            ArticlesDTO _DTO = new ArticlesDTO();
            SearchCriteria _searchCriteria = new SearchCriteria();
            _searchCriteria.addParameter("@ARTICLE_ID", postid );
            BaseList<Article> _articles = (BaseList<Article>)_DTO.Select("SQL_SELECT_ARTICLE_BY_ID", _searchCriteria);

            foreach (Article _article in _articles)
            {
                PublisherService _pService = new PublisherService();
                _article.PublisherEntity = (Publisher)_pService.getPublisherByID(_article.Publisher_ID);
            }

            if (0 == _articles.Count)
                throw new ArticleNotFoundException();

            return _articles[0];
        }

        public void deleteArticle(Article article)
        {
            ArticlesDTO _DTO = new ArticlesDTO();
            SearchCriteria _searchCriteria = new SearchCriteria();
            _searchCriteria.addParameter("@ARTICLE_ID", article.Article_ID);
            _DTO.Select("SQL_DELETE_ARTICLE_BY_ID", _searchCriteria);
        }

        public void UpdateArticle(Article article)
        {
            throw new NotImplementedException();
        }

        public List<Article> getArticleByPublisherId(int p)
        {
            ArticlesDTO _DTO = new ArticlesDTO();
            SearchCriteria _searchCriteria = new SearchCriteria();
            _searchCriteria.addParameter("@PUBLISHER_ID", p);
            BaseList<Article> _articles = (BaseList<Article>)_DTO.Select("SQL_SELECT_ARTICLE_BY_PUBLISHER", _searchCriteria);

            foreach (Article _article in _articles)
            {
                PublisherService _pService = new PublisherService();
                _article.PublisherEntity = (Publisher)_pService.getPublisherByID(_article.Publisher_ID);
            }

            return _articles;
        }
    }
}
